我不打算一開始就深入研究 Kubernetes 的各個元件或是資源。就像看科幻小說,如果一上來就直接看背景設定肯定是最無趣的讀法。
我會花幾天時間帶大家使用 Kubernetes 部署你的第一個應用程式,過程中我們會實作:
在這系列的實作中,我將介紹 Pod
、Service
、Deployment
等 Kubernetes 對象的基本概念及其相關特性,確保實作過程的順暢。更詳細的討論將在後續的主題章節中展開。
我們今天的目標是完成 Web API,打包 Image,上傳到容器倉庫 Docker Hub (Container Registry)。示意圖如下:
golang
撰寫 Web API,需要事先安裝 golang
套件。安裝方法可以參考 Download and install - The Go Programming Language。Docker Hub
,事先註冊好帳號。提醒:
如果想要直接在 WSL - Ubuntu 內安裝 golang
,可以使用以下指令:
sudo apt install golang-go
go version
---
go version go1.18.1 linux/amd64
foo
資料夾,並進入其中。這將會是我們應用的根目錄。檔案: main.go
package main
import (
"net/http"
"os"
"time"
"github.com/gin-gonic/gin"
)
func main() {
hostname, _ := os.Hostname()
started := time.Now()
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "foo")
})
r.GET("/hostname", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"hostname": hostname,
})
})
r.GET("/healthy", func(c *gin.Context) {
c.Status(http.StatusOK)
})
r.GET("/healthy_test", func(c *gin.Context) {
duration := time.Since(started)
if duration.Seconds() > 30 {
c.Status(http.StatusServiceUnavailable)
} else {
c.Status(http.StatusOK)
}
})
r.Run()
}
上述檔案使用 golang
和 gin package 撰寫的 Web API,提供以下端點:
/
: 返回固定訊息。/hostname
: 返回系統主機名稱。/healthy
: 作為健康檢查端點,恆定返回 HTTP 200 狀態碼。/healthy_test
: 作為探針測試端點,啟動後 30 秒內返回 HTTP 200,之後返回 HTTP 503。將上述內容複製儲存到 foo
資料夾內,命名為 main.go
初始化專案
go mod init example.com/foo
go get -u github.com/gin-gonic/gin
go mod tidy
go run main.go
---
[GIN-debug] GET / --> main.main.func1 (3 handlers)
[GIN-debug] GET /hostname --> main.main.func2 (3 handlers)
[GIN-debug] GET /healthy --> main.main.func3 (3 handlers)
[GIN-debug] GET /healthy_test --> main.main.func4 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
curl 0.0.0.0:8080
---
foo
我們繼續在 foo
目錄下進行操作。
Docker 組態檔: Dockerfile
FROM golang:latest AS builder
WORKDIR /
COPY go.mod go.sum ./
RUN go mod download
COPY *.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -o main
FROM alpine:latest
WORKDIR /
COPY --from=builder ./main .
EXPOSE 8080
CMD [ "./main" ]
build 用到的指令:
CGO
是 Go 語言用來調用 C 語言代碼的工具。默認情況下,CGO 是啟用的,這意味著構建過程中可能會依賴於系統的 C 編譯器和標準庫。在 Docker 容器中,這可能導致兼容性問題,尤其是當你從一個環境(如 macOS)構建並在另一個環境(如 Alpine Linux)運行時。因此,通過設置CGO_ENABLED=0
禁用 CGO,可以確保構建出的二進位文件是純 Go 的,不依賴於任何 C 庫,從而提高了可攜性。設置
GOOS=linux
可以確保構建出的二進位文件是針對 Linux 操作系統的,即使構建是在其他操作系統(如 macOS 或 Windows)上進行的。這對於在 Linux 基於 Docker 容器中運行的應用程式來說是至關重要的。
將 Dockerfile
內容複製儲存到 foo
資料夾內,命名為 Dockerfile
編譯為 Image
docker build -t foo .
docker run --rm -p 8080:8080 -it -d foo
curl 0.0.0.0:8080
---
foo
這樣我們就完成了應用的容器化。
接下來,我們要將容器的映像檔推送到容器倉庫,下面的實作會用我自己的帳號 lofairy
作為演示,各位要操作記得換成自己的帳號。
docker tag hello lofairy/foo:latest
docker push lofairy/foo
做到這裡我們的應用就算全部完成了。下面我們來驗證 Image 是否可以正常執行。
docker run --rm -p 8080:8080 -it -d lofairy/foo
curl 0.0.0.0:8080
---
foo